<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>~/jjj/ntl-10.1.0dev/doc/vector.cpp.html</title>
<meta name="Generator" content="Vim/7.4">
<meta name="plugin-version" content="vim7.4_v2">
<meta name="syntax" content="cpp">
<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
<meta name="colorscheme" content="macvim">
<style type="text/css">
<!--
pre { white-space: pre-wrap; font-family: monospace; color: #000000; background-color: #ffffff; }
body { font-family: monospace; color: #000000; background-color: #ffffff; }
* { font-size: 1em; }
.Statement { color: #b03060; font-weight: bold; }
.Comment { color: #0000ee; font-style: italic; }
.Type { color: #008b00; font-weight: bold; }
-->
</style>

<script type='text/javascript'>
<!--

-->
</script>
</head>
<body>
<pre id='vimCodeElement'>


<span class="Comment">/*</span><span class="Comment">*************************************************************************\</span>

<span class="Comment">MODULE: vector</span>

<span class="Comment">SUMMARY:</span>

<span class="Comment">Template class for dynamic-sized vectors.</span>

<span class="Comment">The declaration</span>

<span class="Comment">   Vec&lt;T&gt; v;</span>

<span class="Comment">creates a zero-length vector.  To grow this vector to length n,</span>
<span class="Comment">execute</span>

<span class="Comment">   v.SetLength(n)</span>

<span class="Comment">This causes space to be allocated for (at least) n elements, and also</span>
<span class="Comment">causes the delault constructor for T to be called to initialize these</span>
<span class="Comment">elements.</span>

<span class="Comment">The current length of a vector is available as v.length().</span>

<span class="Comment">The i-th vector element (counting from 0) is accessed as v[i].  If the</span>
<span class="Comment">macro NTL_RANGE_CHECK is defined, code is emitted to test if 0 &lt;= i &lt;</span>
<span class="Comment">v.length().  This check is not performed by default.</span>

<span class="Comment">For old-time FORTRAN programmers, the i-th vector element (counting</span>
<span class="Comment">from 1) is accessed as v(i).</span>

<span class="Comment">Let n = v.length().  Calling v.SetLength(m) with m &lt;= n sets the</span>
<span class="Comment">current length of v to m (but does not call any destructors or free</span>
<span class="Comment">any space).  Calling v.SetLength(m) with m &gt; n will allocate space and</span>
<span class="Comment">initialize as necessary, but will leave the values of the already</span>
<span class="Comment">allocated elements unchanged (although their addresses may change).</span>
<span class="Comment">If T has a user-defined default constructor, that is invoked.</span>
<span class="Comment">Otherwise, the new memory locations are &quot;default initialized&quot;.</span>
<span class="Comment">In particular, this means that POD types may be uninitialized.</span>

<span class="Comment">v.MaxLength() is the largest value of n for which v.SetLength(n) was invoked,</span>
<span class="Comment">and is equal to the number of entries that have been initialized.</span>
<span class="Comment">v.SetMaxLength(n) will allocate space for and initialize up to n elements,</span>
<span class="Comment">without changing v.length().</span>

<span class="Comment">When v's destructor is called, all constructed elements will be</span>
<span class="Comment">destructed, and all space will be relinquished.</span>

<span class="Comment">Space is managed using malloc, realloc, and free.  When a vector is</span>
<span class="Comment">grown, a bit more space may be allocated than was requested for</span>
<span class="Comment">efficiency reasons.</span>

<span class="Comment">Note that when a vector is grown, the space is reallocated using</span>
<span class="Comment">realloc, and thus the addresses of vector elements may change,</span>
<span class="Comment">possibly creating dangling references to vector elements.  One has to</span>
<span class="Comment">be especially careful of this when using vectors passed as reference</span>
<span class="Comment">parameters that may alias one another.</span>

<span class="Comment">Because realloc is used to grow a vector, the objects stored</span>
<span class="Comment">in a vector should be &quot;relocatable&quot;---that is, they shouldn't care</span>
<span class="Comment">what their actual address is, which may change over time.</span>
<span class="Comment">Most reasonable objects satisfy this constraint.</span>

<span class="Comment">v.allocated() is the number of elements which have been allocated,</span>
<span class="Comment">which may be more than the number elements initialized.</span>
<span class="Comment">Note that if n &lt;= v.allocated(), then v.SetLength(n) is guaranteed</span>
<span class="Comment">not to cause any memory allocation, or movement of objects.</span>

<span class="Comment">IMPLEMENTATION DETAILS:</span>

<span class="Comment">A Vec&lt;T&gt; object is just a pointer to the first element of the array.</span>
<span class="Comment">There is a control block immediately before the first element that</span>
<span class="Comment">keeps track of several parameters: </span>
<span class="Comment">   len    -- the logical length of the array (returned by length())</span>
<span class="Comment">   init   -- the number of elements constructed (returned ny MaxLength())</span>
<span class="Comment">   alloc  -- the number of elements for which space has been allocated</span>
<span class="Comment">             (returned by allocated())</span>
<span class="Comment">   fixed  -- flag that indicates that the length is fixed </span>
<span class="Comment">             (returned by fixed())</span>

<span class="Comment">Note that 0 &lt;= len &lt;= init &lt;- alloc</span>

<span class="Comment">COMPARISON TO STL VECTORS:</span>

<span class="Comment">When the length of an NTL vector is reduced, no objects are destroyed.</span>
<span class="Comment">In contrast, when the length of an STL vector is reduced, objects are</span>
<span class="Comment">destroyed (effectively, maintaining the invariant len == init).</span>

<span class="Comment">When the length of an NTL vector is increased, and the new value of len</span>
<span class="Comment">exceeds the current value of alloc, the underying array of objects is</span>
<span class="Comment">resized using malloc.  This implies that existing objects are moved using</span>
<span class="Comment">a bit-wise copy.  As mentioned above, this means that objects should</span>
<span class="Comment">be &quot;relocatable&quot;, in the sense that they do not care what their actual</span>
<span class="Comment">address is.  Most reasonable objects satisfy this constraint.  An example</span>
<span class="Comment">of an object that does not is one that stores in one data member a pointer</span>
<span class="Comment">to another data member within the same object.</span>

<span class="Comment">In contrast, when the length of an STL vector is increased, an new array</span>
<span class="Comment">is allocated, and objects from the old array are copied to the new array,</span>
<span class="Comment">and then destroyed in the old array.  This obviously is much more expensive</span>
<span class="Comment">that NTL's strategy.  However, the new &quot;move semantics&quot;, introduced in C++11,</span>
<span class="Comment">mitigate this issue somewhat.</span>

<span class="Comment">Because of NTL's relocatability requirement, it is not recommended to use NTL</span>
<span class="Comment">vectors over classes coming from the standard library, which may not satisfy</span>
<span class="Comment">the requirement.  In those cases, you could either use an STL vector, or use an</span>
<span class="Comment">NTL vector and wrap the suspect classes in an NTL smart pointer of some kind</span>
<span class="Comment">(e.g., SmartPtr or CopiedPtr).</span>

<span class="Comment">Note also that Facebook's open source &quot;folly&quot; library also provides</span>
<span class="Comment">a vector class that uses realloc in a manner very similar to NTL's vector class.</span>
<span class="Comment">See <a href="https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md">https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md</a></span>



<span class="Comment">\*************************************************************************</span><span class="Comment">*/</span>


<span class="Comment">// EXCEPTIONS: all functions below do not throw any exceptions,</span>
<span class="Comment">//   except as noted</span>

<span class="Type">template</span>&lt;<span class="Type">class</span> T&gt;
<span class="Type">class</span> Vec {
<span class="Statement">public</span>:

   Vec();  <span class="Comment">// initially length 0</span>

   Vec(<span class="Type">const</span> Vec&lt;T&gt;&amp; a);
   <span class="Comment">// copy constructor;  uses the assignment operator of T</span>
   <span class="Comment">// for copying into locations that have already been initialized,</span>
   <span class="Comment">// and uses the copy constructor for T for initializing new locations.</span>

   <span class="Comment">// EXCEPTIONS: may throw</span>

   Vec&amp; <span class="Statement">operator</span>=(<span class="Type">const</span> Vec&lt;T&gt;&amp; a);
   <span class="Comment">// assignment;  uses the assignment operator of T</span>
   <span class="Comment">// for copying into locations that have already been initialized,</span>
   <span class="Comment">// and uses the copy constructor for T for initializing new locations.</span>

   <span class="Comment">// EXCEPTIONS: weak ES (but if it throws, neither length nor MaxLength</span>
   <span class="Comment">//    will change, although some previously initialized elements</span>
   <span class="Comment">//    may have been assigned new values).</span>

   ~Vec();
   <span class="Comment">// destructor: calls T's destructor for all initialized</span>
   <span class="Comment">// elements in the vector, and then frees the vector itself</span>

   <span class="Type">void</span> SetLength(<span class="Type">long</span> n);
   <span class="Comment">// set current length to n, growing vector if necessary</span>
   <span class="Comment">// new objects are initialized using the default contructor for T</span>

   <span class="Comment">// EXCEPTIONS: strong ES (but the vector may have been</span>
   <span class="Comment">//    reallocated)</span>

   <span class="Type">void</span> SetLength(<span class="Type">long</span> n, <span class="Type">const</span> T&amp; a);
   <span class="Comment">// set current length to n, growing vector if necessary</span>
   <span class="Comment">// new objects are initialized using the copy contructor for T</span>

   <span class="Comment">// EXCEPTIONS: strong ES (but the vector may have been</span>
   <span class="Comment">//    reallocated)</span>

   <span class="Type">template</span>&lt;<span class="Type">class</span> F&gt;
   <span class="Type">void</span> SetLengthAndApply(<span class="Type">long</span> n, F f);
   <span class="Comment">// set current length to n, growing vector if necessary</span>
   <span class="Comment">// any new objects are initialized using defauly constructor</span>
   <span class="Comment">// for T, and after that, f is applied to each new object x</span>
   <span class="Comment">// as f(x).</span>

   <span class="Comment">// EXCEPTIONS: strong ES (but the vector may have been</span>
   <span class="Comment">//    reallocated)</span>

   <span class="Type">long</span> length() <span class="Type">const</span>;
   <span class="Comment">// current length</span>

   T&amp; <span class="Statement">operator</span>[](<span class="Type">long</span> i);
   <span class="Type">const</span> T&amp; <span class="Statement">operator</span>[](<span class="Type">long</span> i) <span class="Type">const</span>;
   <span class="Comment">// indexing operation, starting from 0.</span>
   <span class="Comment">// The first version is applied to non-const Vec&lt;T&gt;,</span>
   <span class="Comment">// and returns a non-const reference to a T, while the second version</span>
   <span class="Comment">// is applied to a const Vec&lt;T&gt; and returns a const reference to a T.</span>

   <span class="Comment">// EXCEPTIONS: may throw if range checking turned on, strong ES</span>

   T&amp; <span class="Statement">operator</span>()(<span class="Type">long</span> i);
   <span class="Type">const</span> T&amp; <span class="Statement">operator</span>()(<span class="Type">long</span> i) <span class="Type">const</span>;
   <span class="Comment">// indexing operation, starting from 1</span>
   <span class="Comment">// The first version is applied to non-const Vec&lt;T&gt;,</span>
   <span class="Comment">// and returns a non-const reference to a T, while the second version</span>
   <span class="Comment">// is applied to a const Vec&lt;T&gt; and returns a const reference to a T.</span>

   <span class="Comment">// EXCEPTIONS: may throw if range checking turned on, strong ES</span>

   T* elts();
   <span class="Type">const</span> T* elts() <span class="Type">const</span>;
   <span class="Comment">// returns address of first vector element (or 0 if no space has been</span>
   <span class="Comment">// allocated for this vector).  If a vector potentially has length 0, it is</span>
   <span class="Comment">// safer to write v.elts() instead of &amp;v[0]: the latter is not well defined</span>
   <span class="Comment">// by the C++ standard (although this is likely an academic concern).</span>
   <span class="Comment">//</span>
   <span class="Comment">// The first version is applied to non-const Vec&lt;T&gt;, and returns a non-const</span>
   <span class="Comment">// pointer to a T, while the second version is applied to a const Vec&lt;T&gt; and</span>
   <span class="Comment">// returns a const reference to a T.</span>


   <span class="Type">void</span> swap(Vec&lt;T&gt;&amp; y);
   <span class="Comment">// swap with y (fast: just swaps pointers)</span>

   <span class="Comment">// EXCEPTIONS: throws if vectors are fixed and lengths do not match, strong ES</span>

   <span class="Type">void</span> append(<span class="Type">const</span> T&amp; a);
   <span class="Comment">// append a to end of vector; uses the assignment operator of T</span>
   <span class="Comment">// for copying into locations that have already been initialized,</span>
   <span class="Comment">// and uses the copy constructor for T for initializing new locations.</span>

   <span class="Comment">// EXCEPTIONS: strong ES if initializing a new element (and in any </span>
   <span class="Comment">//    case, if an exception throws, length and MaxLength remain </span>
   <span class="Comment">//    unchanged).</span>

   <span class="Type">void</span> append(<span class="Type">const</span> Vec&lt;T&gt;&amp; w);
   <span class="Comment">// append w to end of vector; uses the assignment operator of T</span>
   <span class="Comment">// for copying into locations that have already been initialized,</span>
   <span class="Comment">// and uses the copy constructor for T for initializing new locations.</span>

   <span class="Comment">// EXCEPTIONS: strong ES if initializing new elements (and in any </span>
   <span class="Comment">//    case, if an exception throws, length and MaxLength remain </span>
   <span class="Comment">//    unchanged).</span>


<span class="Comment">// Alternative access interface </span>

   <span class="Type">const</span> T&amp; get(<span class="Type">long</span> i) <span class="Type">const</span>;
   <span class="Comment">// v.get(i) returns v[i]</span>

   <span class="Type">void</span> put(<span class="Type">long</span> i, <span class="Type">const</span> T&amp; a);
   <span class="Comment">// v.put(i, a) equivalent to v[i] = q</span>



<span class="Comment">// Some STL compatibility</span>

   <span class="Type">typedef</span> T value_type;
   <span class="Type">typedef</span> value_type&amp; reference;
   <span class="Type">typedef</span> <span class="Type">const</span> value_type&amp; const_reference;
   <span class="Type">typedef</span> value_type *iterator;
   <span class="Type">typedef</span> <span class="Type">const</span> value_type *const_iterator;

   T* data();
   <span class="Type">const</span> T* data() <span class="Type">const</span>;
   <span class="Comment">// v.data() same as v.elts()</span>

   T* begin();
   <span class="Type">const</span> T* begin() <span class="Type">const</span>;
   <span class="Comment">// v.begin() same as v.elts()</span>

   T* end();
   <span class="Type">const</span> T* end() <span class="Type">const</span>;
   <span class="Comment">// pointer to last element (or NULL)</span>

   T&amp; at(<span class="Type">long</span> i);
   <span class="Type">const</span> T&amp; at(<span class="Type">long</span> i) <span class="Type">const</span>;
   <span class="Comment">// indexing with range checking</span>


<span class="Comment">// the remaining member functions are a bit esoteric (skip on first</span>
<span class="Comment">// reading)</span>

   Vec(INIT_SIZE_TYPE, <span class="Type">long</span> n);
   <span class="Comment">// Vec(INIT_SIZE, n) initializes vector with an intial length of n.</span>
   <span class="Comment">// new objects are initialized using the default contructor for T</span>

   <span class="Comment">// EXCEPTIONS: may throw</span>

   Vec(INIT_SIZE_TYPE, <span class="Type">long</span> n, <span class="Type">const</span> T&amp; a);
   <span class="Comment">// Vec(INIT_SIZE, n, a) initializes vector with an intial length of n.</span>
   <span class="Comment">// new objects are initialized using the copy contructor for T</span>

   <span class="Comment">// EXCEPTIONS: may throw</span>

   <span class="Type">void</span> kill();
   <span class="Comment">// release space and set to length 0</span>

   <span class="Type">void</span> SetMaxLength(<span class="Type">long</span> n);
   <span class="Comment">// allocates space and initializes up to n elements. Does not change</span>
   <span class="Comment">// current length</span>

   <span class="Comment">// EXCEPTIONS: may throw, strong ES</span>

   <span class="Type">void</span> FixLength(<span class="Type">long</span> n);
   <span class="Comment">// sets length to n and prohibits all future length changes.</span>
   <span class="Comment">// FixLength may only be invoked immediately after the default</span>
   <span class="Comment">// construction or kill.</span>

   <span class="Comment">// The kill operation is also subsequently prohibited, and swap is</span>
   <span class="Comment">// allowed on fixed length vectors of the same length.</span>

   <span class="Comment">// FixLength is provided mainly to implement Mat&lt;T&gt;, to enforce</span>
   <span class="Comment">// the restriction that all rows have the same length.</span>

   <span class="Comment">// EXCEPTIONS: may throw, strong ES</span>

   <span class="Type">void</span> FixAtCurrentLength();
   <span class="Comment">// fixes the length at the cuurent length and prohibits</span>
   <span class="Comment">// all future length changes.  </span>

   <span class="Comment">// It is required that length() == MaxLength() when called.</span>

   <span class="Comment">// EXCEPTIONS: if length() != MaxLength() and error is raised;</span>
   <span class="Comment">// if length() == 0, a memory allocation error may be raised.</span>
   <span class="Comment">// Strong ES.</span>

   <span class="Type">long</span> fixed() <span class="Type">const</span>;
   <span class="Comment">// test if length has been fixed by FixLength() or FixAtCurrentLength()</span>

   <span class="Type">long</span> MaxLength() <span class="Type">const</span>;
   <span class="Comment">// maximum length, i.e., number of allocated and initialized elements</span>

   <span class="Type">long</span> allocated() <span class="Type">const</span>;
   <span class="Comment">// the number of objects for which space has been allocated, but not</span>
   <span class="Comment">// necessarily initialized;  this may be larger than MaxLength().</span>

   T&amp; RawGet(<span class="Type">long</span> i);
   <span class="Type">const</span> T&amp; RawGet(<span class="Type">long</span> i) <span class="Type">const</span>;
   <span class="Comment">// indexing with no range checking</span>

   <span class="Type">long</span> position(<span class="Type">const</span> T&amp; a) <span class="Type">const</span>;
   <span class="Comment">// returns position of a in the vector, or -1 if it is not there.</span>
   <span class="Comment">// The search is conducted from position 0 to allocated()-1 the vector, </span>
   <span class="Comment">// and an error is raised if the object is found at position MaxLength()</span>
   <span class="Comment">// or higher (in which case a references an uninitialized object).</span>
   <span class="Comment">// Note that if NTL_CLEAN_PTR flag is set, this routine takes</span>
   <span class="Comment">// linear time, and otherwise, it takes constant time.</span>

   <span class="Comment">// EXCEPTIONS: may throw (as indicated above)</span>

   <span class="Type">long</span> position1(<span class="Type">const</span> T&amp; a) <span class="Type">const</span>;
   <span class="Comment">// returns position of a in the vector, or -1 if it is not there.</span>
   <span class="Comment">// The search is conducted from position 0 to length()-1 of the vector.</span>
   <span class="Comment">// Note that if NTL_CLEAN_PTR flag is set, this routine takes</span>
   <span class="Comment">// linear time, and otherwise, it takes constant time.</span>

};


<span class="Comment">/*</span><span class="Comment">*************************************************************************\</span>

<span class="Comment">                       Some utility routines</span>

<span class="Comment">\*************************************************************************</span><span class="Comment">*/</span>


<span class="Type">template</span>&lt;<span class="Type">class</span> T&gt;
<span class="Type">void</span> swap(Vec&lt;T&gt;&amp; x, Vec&lt;T&gt;&amp; y);
<span class="Comment">// swaps x &amp; y; same as x.swap(y)</span>

<span class="Comment">// EXCEPTIONS: same as for swap member function</span>

<span class="Type">template</span>&lt;<span class="Type">class</span> T&gt;
<span class="Type">void</span> append(Vec&lt;T&gt;&amp; v, <span class="Type">const</span> T&amp; a);
<span class="Comment">// appends a to the end of v; same as v.append(a)</span>

<span class="Comment">// EXCEPTIONS: same as for append member function</span>

<span class="Type">template</span>&lt;<span class="Type">class</span> T&gt;
<span class="Type">void</span> append(Vec&lt;T&gt;&amp; v, <span class="Type">const</span> Vec&lt;T&gt;&amp; w);
<span class="Comment">// appends w to the end of v; same as v.append(w)</span>

<span class="Comment">// EXCEPTIONS: same as for append member function</span>



<span class="Comment">/*</span><span class="Comment">*************************************************************************\</span>

<span class="Comment">                             Input/Output</span>


<span class="Comment">The I/O format for a vector v with n elements is:</span>

<span class="Comment">   [v[0] v[1] ... v[n-1]]</span>

<span class="Comment">Uses corresponding I/O operators for T</span>

<span class="Comment">\*************************************************************************</span><span class="Comment">*/</span>

<span class="Type">template</span>&lt;<span class="Type">class</span> T&gt;
istream&amp; <span class="Statement">operator</span>&gt;&gt;(istream&amp;, Vec&lt;T&gt;&amp;);

<span class="Comment">// EXCEPTIONS: may throw, weak ES</span>

<span class="Type">template</span>&lt;<span class="Type">class</span> T&gt;
ostream&amp; <span class="Statement">operator</span>&lt;&lt;(ostream&amp;, <span class="Type">const</span> Vec&lt;T&gt;&amp;);

<span class="Comment">// EXCEPTIONS: may throw, weak ES</span>



<span class="Comment">/*</span><span class="Comment">*************************************************************************\</span>

<span class="Comment">                              Equality Testing</span>

<span class="Comment">\*************************************************************************</span><span class="Comment">*/</span>


<span class="Type">template</span>&lt;<span class="Type">class</span> T&gt;
<span class="Type">long</span> <span class="Statement">operator</span>==(<span class="Type">const</span> Vec&lt;T&gt;&amp; a, <span class="Type">const</span> Vec&lt;T&gt;&amp; b);

<span class="Type">template</span>&lt;<span class="Type">class</span> T&gt;
<span class="Type">long</span> <span class="Statement">operator</span>!=(<span class="Type">const</span> Vec&lt;T&gt;&amp; a, <span class="Type">const</span> Vec&lt;T&gt;&amp; b);


<span class="Comment">/*</span><span class="Comment">*************************************************************************\</span>

<span class="Comment">                  Customized Constructors and Destructors</span>
<span class="Comment"> </span>
<span class="Comment">Esoteric: skip on first reading...also these interfaces are subject to change</span>

<span class="Comment">When new elements in a vector need to be constructed, one of the</span>
<span class="Comment">following routines is called:</span>

<span class="Comment">   void BlockConstruct(T* p, long n); </span>
<span class="Comment">   // invokes T() to initialize p[i] for i = 0..n-1</span>

<span class="Comment">   void BlockConstructFromVec(T* p, long n, const T* q);</span>
<span class="Comment">   // invokes T(q[i]) to initialize p[i] for i = 0..n-1;</span>
<span class="Comment">   // q points to elements from a Vec&lt;T&gt;</span>

<span class="Comment">   void BlockConstructFromObj(T* p, long n, const T&amp; q);</span>
<span class="Comment">   // invokes T(q) to initialize p[i] for i = 0..n-1</span>


<span class="Comment">When a vector is destroyed, the following routine is called:</span>

<span class="Comment">   void BlockDestroy(T* p, long n);</span>
<span class="Comment">   // invokes ~T() on p[i] for i = 0..n-1</span>

<span class="Comment">The default behavior of these routines may be modified by </span>
<span class="Comment">overloading these functions with a custom implementation.</span>

<span class="Comment">EXCEPTIONS:</span>
<span class="Comment">In order to provide exception safe code, the Construct routines</span>
<span class="Comment">should provide strong ES; in particular, if any constructor</span>
<span class="Comment">throws, all newly constructed objects should be destroyed.</span>
<span class="Comment">Moreover, the BlockDestroy routine should not throw at all.</span>


<span class="Comment">In NTL, these routines are overridden for the ZZ_p and GF2E classes,</span>
<span class="Comment">so that many vector entries will be packed into contiguous storage</span>
<span class="Comment">locations.  This reduces the number of invocations of malloc, and</span>
<span class="Comment">increases locality of reference.</span>



<span class="Comment">\*************************************************************************</span><span class="Comment">*/</span>

</pre>
</body>
</html>
<!-- vim: set foldmethod=manual : -->
